package net.wicp.tams.common.apiext;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.Result;
import net.wicp.tams.common.constant.BasePath;
import net.wicp.tams.common.constant.Encoding;
import net.wicp.tams.common.constant.StrPattern;
import net.wicp.tams.common.thread.ThreadPool;

/***
 * 文件加载、操作等辅助类
 * 
 * @author andy.zhou
 *
 */
@Slf4j
public abstract class IOUtil {

	/****
	 * 转换输入流为字符串
	 * 
	 * @param in
	 *            输入流
	 * @param oriEncoding
	 *            源编码格式
	 * @return 转换的字符串
	 * @throws IOException
	 *             转换出错
	 */
	public static String slurp(InputStream in, Encoding oriEncoding) throws IOException {
		StringBuffer out = new StringBuffer();
		byte[] b = new byte[4096];
		for (int n; (n = in.read(b)) != -1;) {
			out.append(new String(b, 0, n, oriEncoding.getEncode()));
		}
		return out.toString();
	}

	public static String slurp(InputStream in) throws IOException {
		return slurp(in, Encoding.UTF8);
	}

	/**
	 * 属性文件转为属性
	 * 
	 * @param filePath
	 *            文件路径
	 * @param classz
	 *            要加载属性文件同jar包的类
	 * @return Properties 属性对象
	 */
	@SuppressWarnings("rawtypes")
	public static Properties fileToProperties(String filePath, Class classz) {
		Properties returnPro = new Properties();
		InputStream inputFile = null;
		try {
			inputFile = fileToInputStream(filePath, classz);
			returnPro.load(inputFile);
		} catch (FileNotFoundException e) {
			log.error("找不到文件{}", filePath);
		} catch (Exception e) {
			log.error("读取属性文件{}错误", filePath);
		} finally {
			if (inputFile != null) {
				try {
					inputFile.close();
				} catch (IOException e) {
					log.error("关闭流出错");
				}
			}
		}
		return returnPro;
	}

	/***
	 * 文件转为prop
	 * 
	 * @param filePath
	 *            属性文件
	 * @return 文件中列举的属性值
	 */
	public static Properties fileToProperties(File filePath) {
		Properties returnPro = new Properties();
		InputStream inputFile = null;
		try {
			inputFile = new FileInputStream(filePath);
			returnPro.load(inputFile);
		} catch (FileNotFoundException e) {
			log.error("找不到文件{}", filePath);
		} catch (IOException e) {
			log.error("读取属性文件{}错误", filePath);
		} finally {
			if (inputFile != null) {
				try {
					inputFile.close();
				} catch (IOException e) {
					log.error("关闭流出错");
				}
			}
		}
		return returnPro;
	}

	/****
	 * 通过class加载文件
	 * 
	 * @param filePath
	 *            文件所在路径
	 * @param classz
	 *            文件所在jar包中的class名
	 * @return 文件对应的输入流
	 */
	@SuppressWarnings("rawtypes")
	public static InputStream fileToInputStream(String filePath, Class classz) {
		InputStream inputFile = null;
		if (StringUtil.isNull(filePath)) {
			return null;
		}
		filePath = filePath.replace("\\", "/");
		log.info("--------filePath:{}-------------", filePath);
		if (classz != null) {
			inputFile = classz.getResourceAsStream(filePath);
			if (inputFile == null && !filePath.startsWith("/") && !filePath.startsWith("\\")) {
				inputFile = classz.getResourceAsStream("/" + filePath);
			}
		} else {
			inputFile = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
		}
		return inputFile;
	}

	/***
	 * 得到指定根目录下的属性文件（只要common-开头的jar文件）
	 * 
	 * @param propFilePre
	 *            属性文件的前缀
	 * @param root
	 *            根目录
	 * @param jarpre
	 *            是过滤的jar包前缀
	 * @param firstConfs
	 *            需要首先加载的文件名
	 * @return [0] 要首先加载的系统配置文件 [1] 其次加载的用户配置文件
	 */
	public static List<InputStream>[] findProps(String propFilePre, URL root, String jarpre, String... firstConfs) {
		List<InputStream> firstlist = new ArrayList<>();
		List<InputStream> secondlist = new ArrayList<>();
		String properPattern = String.format(Conf.proPatternFomate, propFilePre);
		if ("jar".equals(root.getProtocol())) {
			try {
				Map<String, InputStream> is = IOUtil.getFilesFromJar(root.getPath(), ".", "properties");
				String fileDir = IOUtil.getCurFolder(Conf.class, false).getPath();
				File dir = new File(IOUtil.mergeFolderAndFilePath(fileDir, "/temp"));
				if (!dir.exists()) {
					dir.mkdir();
				}
				for (String key : is.keySet()) {
					if (key.contains("/" + jarpre) && key.contains(".jar")) {// 微服务里，jar包套jar包
						// log.info("commjar:{}",key);
						String[] paths = key.split("/");
						File newFile = new File(dir, paths[paths.length - 1]);
						log.info("newfile:{}", newFile.getPath());
						if (!newFile.exists()) {
							FileUtils.copyInputStreamToFile(is.get(key), newFile);
						}
						String filepathTrue = newFile.getPath().startsWith("file:") ? "jar:" + newFile.getPath()
								: "jar:file:" + newFile.getPath();
						// log.info("------------proppath:{}----------",filepathTrue);
						Map<String, InputStream> map2 = IOUtil.getFilesFromJar(filepathTrue, ".", "properties");
						for (String key2 : map2.keySet()) {
							if (StrPattern.checkStrFormat(properPattern, key2)) {
								firstlist.add(map2.get(key2));
								// Properties returnPro = new Properties();
								// returnPro.load(map2.get(key2));
								// overProp(returnPro);
							}
						}
					} else if (StrPattern.checkStrFormat(properPattern, key)) {// 一般的jar包
						firstlist.add(is.get(key));
						// Properties returnPro = new Properties();
						// returnPro.load(is.get(key));
						// overProp(returnPro);
					}
				}
			} catch (Exception e) {
				log.error("加载properties错误", e);
			}

		} else if ("file".equals(root.getProtocol())) {
			File dir = new File(root.getPath());
			FileFilter fileFilter = new RegexFileFilter(properPattern);
			File[] files = dir.listFiles(fileFilter);
			for (File file : files) {
				try {
					FileInputStream fileInputStream = new FileInputStream(file);
					if (!ArrayUtils.contains(firstConfs, file.getName())) {
						secondlist.add(fileInputStream);
					} else {
						firstlist.add(fileInputStream);
					}
				} catch (FileNotFoundException e) {
					log.error("读文件错误", e);
				}

				// Properties properties = IOUtil.fileToProperties(file);
				// overProp(properties);
			}
		}
		return new List[] { firstlist, secondlist };
	}

	/***
	 * classpath的属性文件转为属性
	 * 
	 * @param filePath
	 *            文件路径
	 * @return 属性
	 */
	public static Properties fileToProperties(String filePath) {
		return fileToProperties(filePath, null);
	}

	/**
	 * 合并目录与文件名
	 * 
	 * @param folderPath
	 *            目录路径
	 * @param fileName
	 *            文件名
	 * @return String 合并后的文件路径
	 */
	private static String mergeFolderAndFilePath(String folderPath, String fileName) {
		if (StringUtils.isBlank(folderPath)) {
			return fileName;
		}
		if (StringUtils.isBlank(fileName)) {
			return folderPath;
		}
		folderPath = folderPath.replace("\\", "/");
		fileName = fileName.replace("\\", "/");

		if (folderPath.endsWith("/")) {
			folderPath = folderPath.substring(0, folderPath.length() - 1);
		}
		if (fileName.startsWith("/")) {
			fileName = fileName.substring(1);
		}
		return String.format("%s/%s", folderPath, fileName);
	}

	public static String mergeFolderAndFilePath(String folderPath, String... paths) {
		if (ArrayUtils.isEmpty(paths)) {
			return folderPath;
		}
		String retstr = folderPath;
		for (String path : paths) {
			retstr = mergeFolderAndFilePath(retstr, path);
		}
		return retstr;
	}

	/***
	 * 得到指定Class下的文件的目录
	 * 
	 * @param classStr
	 *            指定的class
	 * @param filePath
	 *            文件的相对路径
	 * @return 目录
	 */
	@SuppressWarnings("rawtypes")
	public static String getDirForFilePath(Class classStr, String filePath) {
		URL url = classStr.getResource(filePath);
		int lastIndex = url.getPath().lastIndexOf("/");
		if (lastIndex > 0) {
			return url.getPath().substring(0, lastIndex);
		}
		return null;
	}

	/***
	 * 得到此项目下的文件目录路径
	 * 
	 * @param filePath
	 *            文件路径
	 * @return 真实路径
	 */
	public static String getDirForCommonUtilFilePath(String filePath) {
		return getDirForFilePath(IOUtil.class, filePath);
	}

	/***
	 * 把InputStream复制到OutputStream
	 * 
	 * @param from
	 *            输入流
	 * @param to
	 *            输出流
	 * @return 流字节数
	 * @throws IOException
	 *             操作异常
	 */
	public static long copyInToOut(InputStream from, OutputStream to) throws IOException {
		byte[] buf = new byte[1024];
		long total = 0;
		while (true) {
			int r = from.read(buf);
			if (r == -1) {
				break;
			}
			to.write(buf, 0, r);
			total += r;
		}
		return total;
	}

	/***
	 * 把源模板文件替换为符合条件的目的文件
	 * 
	 * @param oriPath
	 *            源文件路径
	 * @param destPath
	 *            目标文件路径
	 * @param oriEncoding
	 *            源文件编码
	 * @param destEncoding
	 *            目标文件编码
	 * @param replaceRule
	 *            替换规则
	 * @throws IOException
	 *             IO异常
	 */
	public static void replaceFile(String oriPath, String destPath, Encoding oriEncoding, Encoding destEncoding,
			String... replaceRule) throws IOException {
		String strs = FileUtils.readFileToString(new File(oriPath), oriEncoding.getEncode());
		replaceFileByStr(strs, destPath, oriEncoding, destEncoding, replaceRule);
	}

	/***
	 * 代码文件内容并写文件
	 * 
	 * @param oriContext
	 *            要处理的文件内容
	 * @param destPath
	 *            目标文件路径
	 * @param oriEncoding
	 *            源文件编码
	 * @param destEncoding
	 *            目标文件编码
	 * @param replaceRule
	 *            替换规则
	 * @throws IOException
	 *             IO异常
	 */
	public static void replaceFileByStr(String oriContext, String destPath, Encoding oriEncoding, Encoding destEncoding,
			String... replaceRule) throws IOException {
		if (ArrayUtils.isNotEmpty(replaceRule) && replaceRule.length >= 2) {
			for (int i = 0; i < replaceRule.length / 2; i++) {
				oriContext = oriContext.replaceAll(replaceRule[2 * i], replaceRule[2 * i + 1]);
			}
		}
		File destfile = new File(destPath);
		FileUtils.writeStringToFile(destfile, oriContext, destEncoding.getEncode());
	}

	/***
	 * 代码文件内容并写文件,用UTF-8方法
	 * 
	 * @param oriContext
	 *            要处理的文件内容
	 * @param destPath
	 *            目标文件路径
	 * @param replaceRule
	 *            替换规则
	 * @throws IOException
	 *             IO异常
	 */
	public static void replaceFileByStr(String oriContext, String destPath, String... replaceRule) throws IOException {
		replaceFileByStr(oriContext, destPath, Encoding.UTF8, Encoding.UTF8, replaceRule);
	}

	/***
	 * 代码文件内容并写文件,用UTF-8方法
	 * 
	 * @param oriContext
	 *            要处理的文件内容
	 * @param basePath
	 *            基础路径
	 * @param relaPath
	 *            相对路径
	 * @param replaceRule
	 *            替换规则
	 * @throws IOException
	 *             IO异常
	 */
	public static void replaceFileByStr(String oriContext, BasePath basePath, String relaPath, String... replaceRule)
			throws IOException {
		String path = IOUtil.mergeFolderAndFilePath(basePath.getPath(), relaPath);
		replaceFileByStr(oriContext, path, replaceRule);
	}

	/***
	 * 把源模板文件替换为符合条件的目的文件，用UTF-8编码
	 * 
	 * @param oriPath
	 *            源文件路径
	 * @param destPath
	 *            目标文件路径
	 * @param replaceRule
	 *            替换规则
	 * @throws IOException
	 *             IO异常
	 */
	public static void replaceFile(String oriPath, String destPath, String... replaceRule) throws IOException {
		replaceFile(oriPath, destPath, Encoding.UTF8, Encoding.UTF8, replaceRule);
	}

	/***
	 * 按规则替换整个目录下的文件
	 * 
	 * @param oriPath
	 *            源路径
	 * @param destPath
	 *            目的路径
	 * @param replaceRule
	 *            替换规则
	 * @throws IOException
	 *             IO异常
	 */
	public static void replaceDir(String oriPath, String destPath, String... replaceRule) throws IOException {
		Collection<File> files = FileUtils.listFiles(new File(oriPath), TrueFileFilter.INSTANCE,
				TrueFileFilter.INSTANCE);
		for (File file : files) {
			String filepath = file.getPath().replace("\\", "/");
			filepath = filepath.charAt(0) == '/' ? filepath : "/" + filepath;
			String newPath = filepath.replace(oriPath, destPath);
			if (!file.isDirectory()) {// 只处理文件
				IOUtil.replaceFile(file.getPath(), newPath, Encoding.UTF8, Encoding.UTF8, replaceRule);
			} else {
				FileUtils.copyFile(file, new File(newPath));
			}
		}
	}

	/***
	 * 查找jar中的某个目录下的所有文件,dirPath=“.”表示根目录下文件
	 * \D:\greensoft\maven\repository\com\zhongan\plugins\za-maven-plugin\0.1\za
	 * -maven-plugin-0.1.jar!\init\src\main\resources String dirPath = "conf/";
	 * 
	 * @param jarUrlStr
	 *            jar文件路径
	 * @param dirPath
	 *            jar里的目录路径
	 * @param suffix
	 *            要过滤的前缀
	 * @return 指定目录下的所有文件流
	 * @throws Exception
	 *             读文件异常
	 */
	public static Map<String, InputStream> getFilesFromJar(String jarUrlStr, String dirPath, String... suffix)
			throws Exception {
		JarFile jarFile = jarRead(jarUrlStr);
		Enumeration<JarEntry> jarEntrys = jarFile.entries();
		// Assert.assertTrue(jarEntrys.hasMoreElements());
		Map<String, InputStream> retobj = new HashMap<>();
		if (jarEntrys == null || !jarEntrys.hasMoreElements()) {
			return retobj;
		}
		int firstIndex = jarUrlStr.indexOf(".jar!/");
		// file:/home/rjzjh/source/tp/HammerApplication/target/hammer.jar!/BOOT-INF/lib/common-web-3.1.3.jar!/
		int lastIndex = jarUrlStr.endsWith(".jar") ? jarUrlStr.lastIndexOf(".jar") : jarUrlStr.lastIndexOf(".jar!/");
		if (firstIndex == lastIndex) {
			// jar:file:/home/rjzjh/source/tp/HammerApplication/target/hammer.jar!/BOOT-INF/lib/common-apiext-3.1.4.jar!
			lastIndex = jarUrlStr.endsWith(".jar") ? jarUrlStr.lastIndexOf(".jar") : jarUrlStr.lastIndexOf(".jar!");
		}
		// log.info("jarUrlStr:{},firstIndex:{},lastIndex:{}", jarUrlStr,
		// firstIndex, lastIndex);
		while (jarEntrys.hasMoreElements()) {
			JarEntry entry = jarEntrys.nextElement();
			String name = entry.getName();
			boolean need = false;
			if (firstIndex != lastIndex && name.endsWith(".jar")) {// 微服务那种
				need = true;
				// BOOT-INF/classes/是微服务 情况
			} else if (((".".equals(dirPath)
					&& (name.indexOf("/") == -1 || name.replace("BOOT-INF/classes/", "").indexOf("/") == -1))
					|| name.startsWith(dirPath)) && !entry.isDirectory()) {
				if (ArrayUtils.isNotEmpty(suffix)) {
					int lastindex = name.lastIndexOf(".");
					if (lastindex > 0 && ArrayUtils.contains(suffix, name.substring(lastindex + 1))) {
						need = true;
					}
				} else {
					need = true;
				}
			}
			if (need) {
				// 开始读取文件内容
				InputStream is = jarFile.getInputStream(entry);
				retobj.put(name, is);
			}
		}
		return retobj;
	}

	public static JarFile jarRead(String jarUrlStr) throws MalformedURLException, IOException {
		jarUrlStr = jarUrlStr.startsWith("jar:") ? jarUrlStr : String.format("jar:%s", jarUrlStr);
		String jarPath = jarUrlStr.indexOf("!/") > 0 ? jarUrlStr.substring(0, jarUrlStr.indexOf("!/") + 2)
				: (jarUrlStr + "!/");
		URL jarURL = new URL(jarPath);
		JarURLConnection jarCon = (JarURLConnection) jarURL.openConnection();
		JarFile jarFile = jarCon.getJarFile();
		return jarFile;
	}

	/***
	 * 从jar文件里得到指定目录下的class名
	 * 
	 * @param jarUrlStr
	 *            jar文件路径
	 * @param filtDirPath
	 *            jar里的目录路径
	 * @return 指定目录下所有class名
	 * @throws Exception
	 *             读文件异常
	 */
	public static List<String> getClassNameFromJar(String jarUrlStr, String filtDirPath) throws Exception {
		JarFile jarFile = jarRead(jarUrlStr);
		Enumeration<JarEntry> jarEntrys = jarFile.entries();
		List<String> retlist = new ArrayList<>();
		if (jarEntrys == null || !jarEntrys.hasMoreElements()) {
			return retlist;
		}
		while (jarEntrys.hasMoreElements()) {
			JarEntry entry = jarEntrys.nextElement();
			String name = entry.getName();
			if (name.endsWith(".class") && !entry.isDirectory()
					&& (StringUtil.isNull(filtDirPath) ? true : name.startsWith(filtDirPath))) {
				String addstr = name.substring(0, name.length() - 6);
				retlist.add(addstr.replace("/", "."));
			}
		}
		return retlist;
	}

	/***
	 * 指定目录下的class文件
	 * 
	 * @param classDir
	 *            class的目录路径
	 * @param packageName
	 *            指定的的包目录
	 * @return lass的目录下指定包下的所有class文件名
	 */
	public static List<String> getClassNameFromDir(String classDir, String packageName) {
		String classDirTrue = classDir.replace("\\", "/");
		if (StringUtil.isNotNull(packageName)) {
			classDirTrue = IOUtil.mergeFolderAndFilePath(classDirTrue, packageName.replace(".", "/"));
		}
		Collection<File> files = FileUtils.listFiles(new File(classDirTrue), new String[] { "class" }, true);

		List<String> retlist = new ArrayList<>();
		for (File file : files) {
			String filepathTemp = file.getPath().replace("\\", "/");
			filepathTemp = filepathTemp.substring(0, filepathTemp.length() - 6).replace(classDir.replace("\\", "/"),
					"");
			if (filepathTemp.startsWith("/")) {
				filepathTemp = filepathTemp.substring(1);
			}
			filepathTemp = filepathTemp.replace("/", ".");
			retlist.add(filepathTemp);
		}
		return retlist;
	}

	/***
	 * 得到jar里面指定class的子class
	 * 
	 * @param jarUrlStr
	 *            jar文件路径
	 * @param dirPath
	 *            jar里的目录路径
	 * @param parentClassName
	 *            父类的类名
	 * @param pool
	 *            类池
	 * @return 指定目录下的所有的类的类名
	 * @throws Exception
	 *             读文件异常
	 */
	public static List<String> getSubTypeFromJar(String jarUrlStr, String dirPath, String parentClassName,
			ClassPool pool) throws Exception {
		List<String> allClassName = getClassNameFromJar(jarUrlStr, dirPath);
		subClassFilter(allClassName, parentClassName, pool);
		return allClassName;
	}

	/***
	 * 得到指定目录下的指定class的子class
	 * 
	 * @param classDir
	 *            类目录
	 * @param packageName
	 *            类目录下的包名
	 * @param parentClassName
	 *            指定父类
	 * @param pool
	 *            类池
	 * @return 指定目录下的所有的类的类名
	 * @throws Exception
	 *             读文件异常
	 */
	public static List<String> getSubTypeFromDir(String classDir, String packageName, String parentClassName,
			ClassPool pool) throws Exception {
		List<String> allClassName = getClassNameFromDir(classDir, packageName);
		subClassFilter(allClassName, parentClassName, pool);
		return allClassName;
	}

	public static List<String> getSubType(String filepath, String packageName, String parentClassName, ClassPool pool)
			throws Exception {
		File tempfile = new File(filepath);
		if (tempfile.isDirectory()) {
			return getSubTypeFromDir(filepath, packageName, parentClassName, pool);
		} else {
			return getSubTypeFromJar("jar:file:" + ((filepath.charAt(0) == '/') ? "" : "/") + filepath, packageName,
					parentClassName, pool);
		}
	}

	public static void subClassFilter(List<String> allClassName, String parentClassName, ClassPool pool)
			throws NotFoundException {
		final ClassPool pooltrue = pool != null ? pool : ClassPool.getDefault();
		final CtClass superclassTrue = pool.get(parentClassName);
		CollectionUtils.filter(allClassName, new Predicate() {
			@Override
			public boolean evaluate(Object object) {
				try {
					CtClass ctClass = pooltrue.get(String.valueOf(object));
					if (ctClass.subtypeOf(superclassTrue)) {
						return true;
					}
				} catch (Exception e) {// 没有找到子类可以忽略
					return false;
				}
				return false;
			}
		});
	}

	public static boolean isSubClass(String subClass, String parentClassName, ClassPool pool) throws NotFoundException {
		final ClassPool pooltrue = pool != null ? pool : ClassPool.getDefault();
		final CtClass superclassTrue = pool.get(parentClassName);
		CtClass ctClass = pooltrue.get(subClass);
		if (ctClass.subtypeOf(superclassTrue)) {
			return true;
		} else {
			return false;
		}
	}

	public static Set<String> findSubClassByJars(final String parentClassName, int threadnum, Set<String> jars,
			final ClassPool pool) throws Exception {
		final Set<String> sublist = new HashSet<>();
		if (CollectionUtils.isEmpty(jars)) {
			return sublist;
		}
		if (CollectionUtils.isEmpty(jars)) {
			return sublist;
		}
		if (threadnum <= 0)
			threadnum = 1;

		List<String> jarAry = Arrays.asList(jars.toArray(new String[jars.size()]));
		List<List<String>> inputlist = CollectionUtil.splitListN(jarAry, threadnum);
		List<Future<Result>> furlist = new ArrayList<>();

		for (final List<String> jarpaths : inputlist) {
			FutureTask<Result> aa = new FutureTask<Result>(new Callable<Result>() {
				@Override
				public Result call() throws Exception {
					for (String jarpath : jarpaths) {
						try {
							File file = new File(jarpath);
							List<String> templist = IOUtil.getSubType(file.getPath(), null, parentClassName, pool);
							sublist.addAll(templist);
						} catch (Exception e) {
							return Result.getError(String.format("[%s]执行失败", Thread.currentThread().getName()));
						}
					}
					return Result.getSuc(String.format("[%s]执行成功", Thread.currentThread().getName()));
				}
			});
			furlist.add(aa);
			ThreadPool.getDefaultPool().submit(aa);
		}
		for (Future<Result> future : furlist) {
			if (future.get().isSuc()) {
				log.info(future.get().getMessage());
			} else {
				log.info(future.get().getMessage());
			}
		}
		return sublist;
	}

	/***
	 * 得到当前目录 ,不打jar包: file:/D:/source/github/commons/target/classes/
	 * 打jar包:jar所在目录:E:\binlog
	 * 
	 * @param classz
	 *            项目包括的Class
	 * @param isTarget
	 *            是否到根目录,true:去掉classes false:不去掉classes
	 * @return 当前目录
	 */
	public static File getCurFolder(Class<?> classz, boolean isTarget) {
		URL url = classz.getProtectionDomain().getCodeSource().getLocation();
		String filePath = null;
		try {
			filePath = URLDecoder.decode(url.getPath(), "utf-8");// 转化为utf-8编码
		} catch (Exception e) {
			e.printStackTrace();
		}
		boolean isDelClass = false;
		// log.info("filePath111111:{}",filePath);
		if (filePath.endsWith(".jar")) {// 可执行jar包运行的结果里包含".jar"
			// 截取路径中的jar包名
			filePath = filePath.substring(0, filePath.lastIndexOf("/") + 1);
		}
		if (filePath.indexOf("!/") > 0) {// 微服务形式
			// file:/home/rjzjh/source/tp/HammerApplication/target/hammer.jar!/BOOT-INF/lib/common-apiext-3.1.4.jar!/BOOT-INF/lib/common-web-3.1.3.jar
			int endpos = filePath.substring(0, filePath.indexOf("!/")).lastIndexOf("/");
			filePath = filePath.substring(0, endpos);
			filePath = filePath.replace("file:", "");
		} else {// classes
			if (isTarget) {
				isDelClass = true;
			}
		}
		// log.info("filePath111111:{}",filePath);
		File file = new File(filePath);
		if (isDelClass) {
			file = file.getParentFile();
		}
		return file;
	}

	public static File getCurFolder(Class<?> classz) {
		return getCurFolder(classz, false);
	}

	public static List<String> readFileReverse(String filename, int maxNum, String charset, boolean isKipnull) {
		RandomAccessFile rf = null;
		List<String> retlist = new ArrayList<>();
		try {
			rf = new RandomAccessFile(filename, "r");
			long len = rf.length();
			long start = rf.getFilePointer();
			long nextend = start + len - 1;
			String line;
			rf.seek(nextend);
			int c = -1;
			while (nextend > start) {
				c = rf.read();
				if (c == '\n' || c == '\r') {
					line = rf.readLine();
					if (line != null) {
						retlist.add(new String(line.getBytes("ISO-8859-1"), charset));
					} else {
						if (!isKipnull) {
							retlist.add("");
						}
					}
					nextend--;
				}
				nextend--;
				rf.seek(nextend);
				if (nextend == 0) {// 当文件指针退至文件开始处，输出第一行
					retlist.add(new String(rf.readLine().getBytes("ISO-8859-1"), charset));
				}
				if (maxNum > 0 && retlist.size() >= maxNum - 1) {
					break;
				}
			}
		} catch (FileNotFoundException e) {
			return null;
		} catch (IOException e) {
			return null;
		} finally {
			try {
				if (rf != null)
					rf.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return retlist;
	}

	public static List<String> readFileReverse(String filename, int maxNum) {
		return readFileReverse(filename, maxNum, "UTF-8", true);
	}

	/***
	 * 创建指定大小的文件
	 * 
	 * @param fileName
	 *            文件名
	 * @param fileSize
	 *            文件大小
	 * @throws IOException
	 *             创建文件异常
	 */
	public static void createFile(String fileName, long fileSize) throws IOException {
		File newFile = new File(fileName);
		RandomAccessFile raf = new RandomAccessFile(newFile, "rw");
		raf.setLength(fileSize);
		raf.close();
	}

	/***
	 * 得到某个包下的所有class
	 * 
	 * @param pack
	 *            包名
	 * @param inSubPackage
	 *            是否包括子包
	 * @return 查换结果
	 */
	public static Set<Class<?>> getClasses(String pack, boolean inSubPackage) {
		Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
		String packageName = pack;
		String packageDirName = packageName.replace('.', '/');
		Enumeration<URL> dirs;
		try {
			dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
			while (dirs.hasMoreElements()) {
				URL url = dirs.nextElement();
				String protocol = url.getProtocol();
				if ("file".equals(protocol)) {
					String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
					findClassByFile(packageName, filePath, inSubPackage, classes);
				} else if ("jar".equals(protocol)) {
					JarFile jar;
					try {
						jar = ((JarURLConnection) url.openConnection()).getJarFile();
						Enumeration<JarEntry> entries = jar.entries();
						while (entries.hasMoreElements()) {
							JarEntry entry = entries.nextElement();
							String name = entry.getName();
							if (name.charAt(0) == '/') {
								name = name.substring(1);
							}
							if (name.startsWith(packageDirName)) {
								int idx = name.lastIndexOf('/');
								if (idx != -1) {
									packageName = name.substring(0, idx).replace('/', '.');
								}
								if ((idx != -1) || inSubPackage) {
									if (name.endsWith(".class") && !entry.isDirectory()) {
										String className = name.substring(packageName.length() + 1, name.length() - 6);
										try {
											classes.add(Class.forName(packageName + '.' + className));
										} catch (ClassNotFoundException e) {
											e.printStackTrace();
										}
									}
								}
							}
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return classes;
	}

	/**
	 * 以文件的形式来获取包下的所有Class
	 * 
	 * @param packageName
	 *            包名
	 * @param packagePath
	 *            包路径
	 * @param recursive
	 *            是否穷取子孙目录
	 * @param classes
	 *            查到的结果
	 */
	public static void findClassByFile(String packageName, String packagePath, final boolean recursive,
			Set<Class<?>> classes) {
		File dir = new File(packagePath);
		if (!dir.exists() || !dir.isDirectory()) {
			return;
		}
		File[] dirfiles = dir.listFiles(new FileFilter() {
			public boolean accept(File file) {
				return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
			}
		});
		for (File file : dirfiles) {
			if (file.isDirectory()) {
				findClassByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);
			} else {
				String className = file.getName().substring(0, file.getName().length() - 6);
				try {
					classes.add(
							Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static List<URL> findHasPackRootPath(String... packageNames) {
		List<URL> retRoots = new ArrayList<>();
		if (ArrayUtils.isEmpty(packageNames)) {
			return retRoots;
		}
		for (String packageName : packageNames) {
			String packageDirName = packageName.replace('.', '/');
			try {
				Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
				while (dirs.hasMoreElements()) {
					URL url = dirs.nextElement();
					String protocol = url.getProtocol();
					if ("file".equals(protocol)) {
						int index = url.getPath().indexOf("/classes/");
						if (index > 0) {
							String rootpath = url.getPath().substring(0, index + 9);
							URL url2 = new URL("file:" + rootpath);
							if (!retRoots.contains(url2)) {
								retRoots.add(url2);
							}
						}
					} else if ("jar".equals(protocol)) {
						int index = url.getPath().lastIndexOf(".jar!/");
						if (index > 0) {
							String rootpath = url.getPath().substring(0, index + 6);
							URL url2 = new URL("jar:" + rootpath);
							if (!retRoots.contains(url2)) {
								retRoots.add(url2);
							}
						}
					}
				}
			} catch (IOException e) {
				log.error("查根路径错误", e);
			}
		}

		return retRoots;
	}

	/*
	 * public static void main(String[] args) throws Exception { Map<String,
	 * InputStream> rt= getFilesFromJar (
	 * "jar:file:/D:/greensoft/maven/repository/com/zhongan/plugins/za-maven-plugin/0.1/za-maven-plugin-0.1.jar!/init/src/main/resources"
	 * ,"init"); for (String name : rt.keySet()) { System.out.println(name); } }
	 */

}
